"""OneDrive文件操作模块

实现OneDrive的文件管理功能，包括文件列表、下载、删除、重命名等操作。
"""

import os
import hashlib
import json
from typing import Dict, Any, Optional, List
import requests
from ..base_client import BaseCloudClient


class FileOperations:
    """OneDrive文件操作类"""
    
    def __init__(self, client: BaseCloudClient):
        self.client = client
        self.session = client.session
    
    def get_files(self, folder_id: str = "root", page: int = 1, page_size: int = 100) -> Dict[str, Any]:
        """获取文件列表
        
        Args:
            folder_id: 文件夹ID，默认为根目录
            page: 页码
            page_size: 每页大小
            
        Returns:
            文件列表信息
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            # 构建API URL
            if folder_id == "root":
                url = "https://graph.microsoft.com/v1.0/me/drive/root/children"
            else:
                url = f"https://graph.microsoft.com/v1.0/me/drive/items/{folder_id}/children"
            
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            params = {
                "$top": page_size,
                "$skip": (page - 1) * page_size
            }
            
            response = self.session.get(url, headers=headers, params=params)
            
            if response.status_code == 200:
                result = response.json()
                files = []
                
                for item in result.get("value", []):
                    file_info = {
                        "id": item.get("id"),
                        "name": item.get("name"),
                        "size": item.get("size", 0),
                        "type": "folder" if "folder" in item else "file",
                        "md5": item.get("file", {}).get("hashes", {}).get("quickXorHash"),
                        "create_time": item.get("createdDateTime"),
                        "modify_time": item.get("lastModifiedDateTime"),
                        "parent_id": item.get("parentReference", {}).get("id")
                    }
                    files.append(file_info)
                
                return {
                    "success": True,
                    "files": files,
                    "total": len(files),
                    "page": page,
                    "page_size": page_size
                }
            else:
                return {"success": False, "error": f"获取文件列表失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"获取文件列表异常: {str(e)}"}
    
    def get_file_info(self, file_id: str) -> Dict[str, Any]:
        """获取文件信息
        
        Args:
            file_id: 文件ID
            
        Returns:
            文件信息
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            response = self.session.get(url, headers=headers)
            
            if response.status_code == 200:
                item = response.json()
                return {
                    "success": True,
                    "file_info": {
                        "id": item.get("id"),
                        "name": item.get("name"),
                        "size": item.get("size", 0),
                        "type": "folder" if "folder" in item else "file",
                        "md5": item.get("file", {}).get("hashes", {}).get("quickXorHash"),
                        "create_time": item.get("createdDateTime"),
                        "modify_time": item.get("lastModifiedDateTime"),
                        "parent_id": item.get("parentReference", {}).get("id")
                    }
                }
            else:
                return {"success": False, "error": f"获取文件信息失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"获取文件信息异常: {str(e)}"}
    
    def get_download_url(self, file_id: str) -> Dict[str, Any]:
        """获取文件下载链接
        
        Args:
            file_id: 文件ID
            
        Returns:
            下载链接信息
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}/content"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}"
            }
            
            # 使用HEAD请求获取重定向URL
            response = self.session.head(url, headers=headers, allow_redirects=False)
            
            if response.status_code == 302:
                download_url = response.headers.get("Location")
                return {
                    "success": True,
                    "download_url": download_url
                }
            else:
                return {"success": False, "error": f"获取下载链接失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"获取下载链接异常: {str(e)}"}
    
    def download_file(self, file_id: str, local_path: str) -> Dict[str, Any]:
        """下载文件
        
        Args:
            file_id: 文件ID
            local_path: 本地保存路径
            
        Returns:
            下载结果
        """
        try:
            # 获取下载链接
            url_result = self.get_download_url(file_id)
            if not url_result["success"]:
                return url_result
            
            download_url = url_result["download_url"]
            
            # 创建目录
            os.makedirs(os.path.dirname(local_path), exist_ok=True)
            
            # 下载文件
            response = self.session.get(download_url, stream=True)
            
            if response.status_code == 200:
                with open(local_path, 'wb') as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)
                
                return {
                    "success": True,
                    "message": "文件下载成功",
                    "local_path": local_path
                }
            else:
                return {"success": False, "error": f"下载文件失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"下载文件异常: {str(e)}"}
    
    def create_folder(self, name: str, parent_id: str = "root") -> Dict[str, Any]:
        """创建文件夹
        
        Args:
            name: 文件夹名称
            parent_id: 父文件夹ID，默认为根目录
            
        Returns:
            创建结果
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            if parent_id == "root":
                url = "https://graph.microsoft.com/v1.0/me/drive/root/children"
            else:
                url = f"https://graph.microsoft.com/v1.0/me/drive/items/{parent_id}/children"
            
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            data = {
                "name": name,
                "folder": {},
                "@microsoft.graph.conflictBehavior": "rename"
            }
            
            response = self.session.post(url, headers=headers, json=data)
            
            if response.status_code == 201:
                result = response.json()
                return {
                    "success": True,
                    "message": "文件夹创建成功",
                    "folder_id": result.get("id")
                }
            else:
                return {"success": False, "error": f"创建文件夹失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"创建文件夹异常: {str(e)}"}
    
    def delete_file(self, file_id: str) -> Dict[str, Any]:
        """删除文件
        
        Args:
            file_id: 文件ID
            
        Returns:
            删除结果
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}"
            }
            
            response = self.session.delete(url, headers=headers)
            
            if response.status_code == 204:
                return {
                    "success": True,
                    "message": "文件删除成功"
                }
            else:
                return {"success": False, "error": f"删除文件失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"删除文件异常: {str(e)}"}
    
    def delete_folder(self, folder_id: str) -> Dict[str, Any]:
        """删除文件夹
        
        Args:
            folder_id: 文件夹ID
            
        Returns:
            删除结果
        """
        return self.delete_file(folder_id)  # OneDrive中文件和文件夹删除API相同
    
    def rename_file(self, file_id: str, new_name: str) -> Dict[str, Any]:
        """重命名文件
        
        Args:
            file_id: 文件ID
            new_name: 新文件名
            
        Returns:
            重命名结果
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            data = {
                "name": new_name
            }
            
            response = self.session.patch(url, headers=headers, json=data)
            
            if response.status_code == 200:
                return {
                    "success": True,
                    "message": "文件重命名成功"
                }
            else:
                return {"success": False, "error": f"重命名文件失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"重命名文件异常: {str(e)}"}
    
    def rename_folder(self, folder_id: str, new_name: str) -> Dict[str, Any]:
        """重命名文件夹
        
        Args:
            folder_id: 文件夹ID
            new_name: 新文件夹名
            
        Returns:
            重命名结果
        """
        return self.rename_file(folder_id, new_name)  # OneDrive中文件和文件夹重命名API相同
    
    def move_file(self, file_id: str, target_folder_id: str) -> Dict[str, Any]:
        """移动文件
        
        Args:
            file_id: 文件ID
            target_folder_id: 目标文件夹ID
            
        Returns:
            移动结果
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            data = {
                "parentReference": {
                    "id": target_folder_id
                }
            }
            
            response = self.session.patch(url, headers=headers, json=data)
            
            if response.status_code == 200:
                return {
                    "success": True,
                    "message": "文件移动成功"
                }
            else:
                return {"success": False, "error": f"移动文件失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"移动文件异常: {str(e)}"}
    
    def copy_file(self, file_id: str, target_folder_id: str, new_name: str = None) -> Dict[str, Any]:
        """复制文件
        
        Args:
            file_id: 文件ID
            target_folder_id: 目标文件夹ID
            new_name: 新文件名，可选
            
        Returns:
            复制结果
        """
        try:
            if not self.client.check_login_status():
                return {"success": False, "error": "未登录"}
            
            url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}/copy"
            headers = {
                "Authorization": f"Bearer {self.client.access_token}",
                "Content-Type": "application/json"
            }
            
            data = {
                "parentReference": {
                    "id": target_folder_id
                }
            }
            
            if new_name:
                data["name"] = new_name
            
            response = self.session.post(url, headers=headers, json=data)
            
            if response.status_code == 202:
                return {
                    "success": True,
                    "message": "文件复制已开始",
                    "location": response.headers.get("Location")
                }
            else:
                return {"success": False, "error": f"复制文件失败: {response.text}"}
                
        except Exception as e:
            return {"success": False, "error": f"复制文件异常: {str(e)}"}
    
    def calculate_md5(self, file_path: str) -> str:
        """计算文件MD5值
        
        Args:
            file_path: 文件路径
            
        Returns:
            文件的MD5值
        """
        md5_hash = hashlib.md5()
        with open(file_path, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), b""):
                md5_hash.update(chunk)
        return md5_hash.hexdigest()